import base from "./base.js"
import GsCfg from "./gsCfg.js"
import MysInfo from "./mys/mysInfo.js"
import MysApi from "./mys/mysApi.js"
import lodash from "lodash"
import moment from "moment"
import fs from "node:fs"
import common from "../../../lib/common/common.js"
import { Character } from "#miao.models"

export default class Ledger extends base {
  constructor(e) {
    super(e)
    this.e = e
    this.model = "ledger"
    if (this.e.msg?.includes("星琼")) this.e.isSr = true

    this.color = [
      "#73a9c6",
      "#d56565",
      "#70b2b4",
      "#bd9a5a",
      "#739970",
      "#7a6da7",
      "#597ea0",
      "#ffb6c1",
    ]
    this.action = {
      other: 0,
      adventure_reward: 1,
      space_reward: 2,
      daily_reward: 3,
      abyss_reward: 4,
      mail_reward: 5,
      event_reward: 6,
      combat_reward: 7,
    }
  }

  async get() {
    this.getMonth()
    if (!this.month) return

    let res = await MysInfo.get(this.e, "ys_ledger", { month: this.month })
    if (!res || res.retcode !== 0) return false

    this.e.nowData = res.data
    let data = this.dealData(res.data)

    this.saveLedger(this.e.uid)

    return data
  }

  getMonth() {
    let month = this.e.msg.replace(/#|原石|月|札记|星铁|星琼/g, "")
    let NowMonth = Number(moment().month()) + 1
    let monthData = ["一", "二", "三", "四", "五", "六", "七", "八", "九", "十", "十一", "十二"]
    if (month) {
      if (isNaN(month)) {
        for (let i in monthData) {
          if (month == monthData[i]) {
            month = Number(i) + 1
            break
          }
        }
        if (isNaN(month)) {
          month = NowMonth
        }
      }
    } else {
      month = NowMonth
    }
    if (month < 1 || month > 12) {
      month = NowMonth
    }

    // 获取前三个月
    let monthArr = [11, 12, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12].splice(NowMonth - 1, 3)
    if (!monthArr.includes(Number(month))) {
      this.e.reply("札记仅支持查询最近三个月的数据")
      return false
    }
    if (
      (NowMonth >= 3 && month > NowMonth) ||
      (NowMonth < 3 && month > NowMonth && month <= 9 + month)
    ) {
      month = NowMonth
    }
    if (this.e.isSr) {
      this.NowMonth = moment().year().toString() + (NowMonth < 10 ? "0" : "") + NowMonth.toString()
      this.month = moment().year().toString() + (month < 10 ? "0" : "") + month.toString()
      this.srmonth = month
    } else {
      this.NowMonth = NowMonth
      this.month = month
    }
  }

  dealData(ledgerInfo) {
    let day
    if (this.month == this.NowMonth) {
      day = `${this[this.e.isSr ? "srmonth" : "month"]}月${moment().date()}号`
    } else {
      day = `${this[this.e.isSr ? "srmonth" : "month"]}月`
    }

    let gacha = this.e.isSr ? "current_hcoin" : "current_primogems"
    let last_gacha = this.e.isSr ? "last_hcoin" : "last_primogems"
    let mora = this.e.isSr ? "current_rails_pass" : "current_mora"
    let last_mora = this.e.isSr ? "last_rails_pass" : "last_mora"

    ledgerInfo.month_data.gacha = (ledgerInfo.month_data[gacha] / 160).toFixed(0)
    ledgerInfo.month_data.last_gacha = (ledgerInfo.month_data[last_gacha] / 160).toFixed(0)
    if (ledgerInfo.month_data[gacha] > 10000) {
      ledgerInfo.month_data[gacha] = (ledgerInfo.month_data[gacha] / 10000).toFixed(2) + " w"
    }
    if (ledgerInfo.month_data[last_gacha] > 10000) {
      ledgerInfo.month_data[last_gacha] =
        (ledgerInfo.month_data[last_gacha] / 10000).toFixed(2) + " w"
    }
    if (ledgerInfo.month_data[mora] > 10000) {
      ledgerInfo.month_data[mora] = (ledgerInfo.month_data[mora] / 10000).toFixed(1) + " w"
    }
    if (ledgerInfo.month_data[last_mora] > 10000) {
      ledgerInfo.month_data[last_mora] =
        (ledgerInfo.month_data[last_mora] / 10000).toFixed(1) + " w"
    }
    if (ledgerInfo.day_data[gacha] > 10000) {
      ledgerInfo.day_data[gacha] = (ledgerInfo.day_data[gacha] / 10000).toFixed(1) + " w"
    }
    if (ledgerInfo.day_data[mora] > 10000) {
      ledgerInfo.day_data[mora] = (ledgerInfo.day_data[mora] / 10000).toFixed(1) + " w"
    }

    ledgerInfo.color = []
    ledgerInfo.month_data.group_by.forEach(item => {
      if (this.e.isSr) {
        item.color = this.color[this.action[item.action]]
        item.action_name = item.action_name.slice(0, 4)
      } else {
        item.color = this.color[item.action_id]
      }
      ledgerInfo.color.push(item.color)
    })

    ledgerInfo.group_by = JSON.stringify(ledgerInfo.month_data.group_by)
    ledgerInfo.color = JSON.stringify(ledgerInfo.color)

    let iconChar = lodash.sample([
      "希儿",
      "白露",
      "艾丝妲",
      "布洛妮娅",
      "姬子",
      "卡芙卡",
      "克拉拉",
      "停云",
      "佩拉",
      "黑塔",
      "希露瓦",
      "银狼",
    ])
    let char = Character.get(iconChar, "gs")

    let week = ["星期日", "星期一", "星期二", "星期三", "星期四", "星期五", "星期六"]

    return {
      saveId: this.e.uid,
      uid: this.e.uid,
      day,
      icon: char.imgs?.face,
      srday: `${week[moment().day()]}`,
      nowDay: moment(new Date()).format("YYYY年MM月DD日"),
      ...ledgerInfo,
      ...this.screenData,
    }
  }

  // 保存上两个原石数据
  async saveLedger(uid, ck = "", isTask = false) {
    if (ck) {
      uid = ck.uid
    } else {
      /** 获取个人ck */
      ck = await MysInfo.checkUidBing(uid, this.e.isSr ? "sr" : "gs")
    }

    if (!ck || lodash.isEmpty(ck)) {
      return false
    }

    let dataPath = `./data/${this.e?.isSr ? "SR_NoteData" : "NoteData"}/${uid}.json`
    let NoteData = {}
    if (fs.existsSync(dataPath)) {
      NoteData = JSON.parse(fs.readFileSync(dataPath, "utf8"))
    }
    // 当前年
    let NowYear = Number(moment().year())
    let NowMonth = Number(moment().month()) + 1

    // 获取前三个月
    let monthArr = [11, 12, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12].splice(NowMonth - 1, 3)

    for (let month of monthArr) {
      let year = NowYear
      // 上一年
      if (NowMonth <= 2 && month >= 11) {
        year--
      }

      if (!NoteData[year]) NoteData[year] = {}

      if (NoteData[year][month] && NowMonth != month && NoteData[year][month].isUpdate) continue

      let ledgerInfo
      if (NowMonth == month && this.e.nowData && this.e.nowData?.data?.data_month == NowMonth) {
        ledgerInfo = this.e.nowData
      } else {
        let months = month
        if (this.e.isSr) months = String(year) + (month < 10 ? "0" : "") + String(month)

        ledgerInfo = await this.ysLedger(ck, months, isTask)
        if (!ledgerInfo) continue
      }

      if (NowMonth != month) {
        ledgerInfo.isUpdate = true
      }

      NoteData[year][month] = ledgerInfo

      common.sleep(100)
    }

    logger.mark(`[札记查询][自动保存] uid:${uid} 数据已保存`)

    fs.writeFileSync(dataPath, JSON.stringify(NoteData, "", "\t"))
    return NoteData
  }

  async ysLedger(ck, month, isTask) {
    let ledgerInfo = {}
    if (isTask) {
      let mysApi = new MysApi(ck.uid, ck.ck, { log: false }, this.e?.isSr)
      ledgerInfo = await mysApi.getData("ys_ledger", { month })
      ledgerInfo = await new MysInfo(this.e).checkCode(
        ledgerInfo,
        "ys_ledger",
        mysApi,
        { month },
        isTask,
      )
    } else {
      ledgerInfo = await MysInfo.get(this.e, "ys_ledger", { month })
    }

    if (!ledgerInfo || ledgerInfo.retcode != 0) return false

    return ledgerInfo.data
  }

  async ledgerTask(manual) {
    let cks = (await GsCfg.getBingCk(this.e?.isSr ? "sr" : "gs")).ck
    let uids = lodash.map(cks, "uid")
    let finishTime = moment()
      .add(uids.length * 0.7, "s")
      .format("MM-DD HH:mm:ss")
    logger.mark(
      `${this.e?.isSr ? "开拓月历" : "札记"}ck:${uids.length}个，预计需要${this.countTime(uids.length)} ${finishTime} 完成`,
    )

    if (manual) {
      await this.e.reply(`开始任务：保存${this.e?.isSr ? "星琼" : "原石"}数据，完成前请勿重复执行`)
      await this.e.reply(
        `${this.e?.isSr ? "开拓月历" : "札记"}ck：${uids.length}个\n预计需要：${this.countTime(uids.length)}\n完成时间：${finishTime}`,
      )
    }

    for (const uid of uids) {
      const ck = cks[uid]

      await this.saveLedger(uid, ck, true)
      await common.sleep(500)
    }

    if (manual) {
      this.e.reply(`${this.e?.isSr ? "星琼" : "原石"}任务完成`)
    }
  }

  countTime(num) {
    let time = num * 0.7
    let hour = Math.floor((time / 3600) % 24)
    let min = Math.floor((time / 60) % 60)
    let sec = Math.floor(time % 60)
    let msg = ""
    if (hour > 0) msg += `${hour}小时`
    if (min > 0) msg += `${min}分钟`
    if (sec > 0) msg += `${sec}秒`
    return msg
  }

  async ledgerCount() {
    this.model = "ledgerCount"

    let mysInfo = await MysInfo.init(this.e, "ys_ledger")
    let uid = mysInfo?.uid
    if (!uid) return false

    /** 保存札记数据 */
    let NoteData = await this.saveLedger(uid)
    /** 处理数据 */
    return this.ledgerCountData(NoteData)
  }

  async ledgerCountHistory() {
    let nowYear
    if (this.e.msg.includes("去年")) {
      nowYear = moment().year() - 1
    } else if (this.e.msg.includes("今年")) {
      nowYear = moment().year()
    } else {
      // 获取年份
      nowYear = this.e.msg.match(/(\d{4})/)
    }
    if (nowYear) {
      nowYear = parseInt(nowYear)
    }
    if (!nowYear) {
      nowYear = moment().year()
    }
    this.model = "ledgerCount"
    let mysInfo = await MysInfo.init(this.e, "ys_ledger")
    let uid = mysInfo?.uid
    if (!uid) return false
    let dataPath = `./data/${this.e?.isSr ? "SR_NoteData" : "NoteData"}/${uid}.json`
    let NoteData = {}
    if (fs.existsSync(dataPath)) {
      NoteData = JSON.parse(fs.readFileSync(dataPath, "utf8"))
    }
    // console.log(NoteData)
    if (!NoteData || lodash.isEmpty(NoteData)) {
      this.e.reply(this.e?.isSr ? '暂无星琼数据，请先发送 *星琼' : '暂无原石数据，请先发送 #原石', false, { at: true })
      return false
    }
    NoteData = NoteData[nowYear]
    if (!NoteData) {
      this.e.reply(`uid：${uid} ${nowYear}年无${this.e?.isSr ? "星琼" : "原石"}统计数据！`, false, {
        at: true,
      })
      return false
    }
    lodash.forEach(NoteData, val => {
      val.year = nowYear
    })
    /** 处理数据 */
    return this.ledgerCountData(NoteData, String(nowYear))
  }

  ledgerCountData(NoteData, nowYear) {
    let hasMore = false
    let yearText
    if (!nowYear) {
      // 获取总长度
      if (NoteData && Object.keys(NoteData) && Object.keys(NoteData).length > 0) {
        let len = 0
        Object.keys(NoteData).forEach(year => {
          let yearData = NoteData[year]
          len += Object.keys(yearData).length
        })
        hasMore = len >= 12
      }

      // 获取最近12个月的数据
      const newNoteData = []
      for (let i = 0; i < 12; i++) {
        let month = Number(moment().month()) + 1 - i
        let year = Number(moment().year())

        if (month <= 0) {
          month = 12 + month
          year--
        }
        if (NoteData[year] && NoteData[year][month]) {
          NoteData[year][month].year = year
          newNoteData.push(NoteData[year][month])
        }
      }
      NoteData = newNoteData
    } else {
      yearText = `${nowYear}年-`
    }

    if (!NoteData || lodash.isEmpty(NoteData)) return

    let data = {
      allPrimogems: 0,
      allMora: 0,
      primogemsMonth: [],
      moraMonth: [],
      yearText,
    }

    let Primogems = this.e.isSr ? "current_hcoin" : "current_primogems"
    let Mora = this.e.isSr ? "current_rails_pass" : "current_mora"
    lodash.forEach(NoteData, val => {
      data.allPrimogems += val.month_data[Primogems]
      data.allMora += val.month_data[Mora]
      // 柱状图数据
      if (this.e.isSr)
        val.data_month =
          val.data_month.slice(-2, -1) == "0" ? val.data_month.slice(-1) : val.data_month.slice(-2)

      data.primogemsMonth.push({
        value: val.month_data[Primogems],
        month: String(val.data_month),
        year: String(val.year),
        name: this.e.isSr ? "星琼" : "原石",
      })
      data.moraMonth.push({
        value: (val.month_data[Mora] / 1000).toFixed(0),
        month: String(val.data_month),
        year: String(val.year),
        name: this.e.isSr ? "专&通票" : "摩拉",
      })
    })

    // 单位处理
    data.allPrimogemsShow = (data.allPrimogems / 10000).toFixed(2) + "w"
    data.allGacha = (data.allPrimogems / 160).toFixed(0)
    if (this.e.isSr) {
      data.allGacha = (data.allPrimogems / 160 + data.allMora).toFixed(0)
      data.allMora = data.allMora.toFixed(0) + "张"
    } else {
      data.allMora = (data.allMora / 10000).toFixed(0) + "w"
    }

    // 原石最多
    data.maxPrimogems = lodash.maxBy(data.primogemsMonth, "value")
    data.maxMora = lodash.maxBy(data.moraMonth, "value")
    // 按年份月份排序
    data.primogemsMonth = lodash.sortBy(data.primogemsMonth, item => {
      return Number(item.year) * 100 + Number(item.month)
    })

    const groupBy = NoteData.flatMap(i => i.month_data.group_by)

    if (this.e.isSr)
      groupBy.forEach(item => {
        item.action_id = this.action[item.action]
        item.action = item.action_name.slice(0, 4)
      })

    let pieData = {}
    for (let val of groupBy) {
      if (!pieData[val.action]) {
        pieData[val.action] = {
          num: val.num,
          action: val.action,
          action_id: val.action_id,
        }
      } else {
        pieData[val.action].num += val.num
      }
    }

    pieData = lodash.flatMap(pieData, item => item)
    pieData = lodash.orderBy(pieData, ["num"], ["desc"])

    data.color = []
    pieData.forEach(item => {
      data.color.push(this.color[item.action_id])
    })

    data.group_by = pieData

    data.color = JSON.stringify(data.color)
    data.pieData = JSON.stringify(pieData)
    data.primogemsMonth = JSON.stringify(data.primogemsMonth)
    data.hasMore = hasMore

    return {
      saveId: this.e.uid,
      uid: this.e.uid,
      ...data,
      ...this.screenData,
    }
  }
}
